package com.fxnotes.database.inmemory.repository;

import com.google.inject.Inject;
import com.fxnotes.database.inmemory.InMemoryDatabase;
import com.fxnotes.database.inmemory.Query;
import com.fxnotes.domain.model.Book;
import com.fxnotes.domain.model.Chapter;
import com.fxnotes.domain.repository.IBookRepository;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class BookRepository implements IBookRepository {

    private final InMemoryDatabase database;

    @Inject
    public BookRepository(InMemoryDatabase database) {
        this.database = database;
    }

    @Override
    public void add(Book book) throws EntityDuplicateException {
        Collection<Book> result = database.find(Book.class, createQueryByName(book.getName()));
        if (result.isEmpty()) {
            database.store(book);

        } else {
            throw new EntityDuplicateException("Book already exists!");
        }
    }

    @Override
    public void updateName(Book book, String name) throws EntityDuplicateException {
        Collection<Book> result = database.find(Book.class, createQueryByName(name));
        if (result.isEmpty()) {
            book.setName(name);

        } else {
            throw new EntityDuplicateException("Book already exists!");
        }
    }

    @Override
    public void updateChapters(Book book, List<Chapter> chapters) {
        book.getChapters().clear();
        book.getChapters().addAll(chapters);
    }

    @Override
    public void remove(Book book) {
        database.remove(book);
    }

    @Override
    public List<Book> findAll() {
        List<Book> books = database.findAll(Book.class);
        Collections.sort(books, new Comparator<Book>() {

            @Override
            public int compare(Book b1, Book b2) {
                return b1.getName().compareTo(b2.getName());
            }
        });
        return books;
    }

    private Query<Book> createQueryByName(final String name) {
        return new Query<Book>() {

            @Override
            public boolean match(Book book) {
                return book.getName().equals(name);
            }
        };
    }
}
